//---------------------------------------------------------------------------
// MD5 Class
// Author : Woo-Hyun Kim at www.webrobot.org
// Date : Jan. 9, 2002
//---------------------------------------------------------------------------
#ifndef CMD5H
#define CMD5H
//---------------------------------------------------------------------------
// Constants for Transform routine.
//---------------------------------------------------------------------------
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
//---------------------------------------------------------------------------  
// F, G, H and I are basic MD5 functions.
//---------------------------------------------------------------------------
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
//---------------------------------------------------------------------------
// ROTATE_LEFT rotates x left n bits.
//---------------------------------------------------------------------------
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
//---------------------------------------------------------------------------
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
//---------------------------------------------------------------------------
#define FF(a, b, c, d, x, s, ac) { \
   (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
  }
#define GG(a, b, c, d, x, s, ac) { \
   (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
  }
#define HH(a, b, c, d, x, s, ac) { \
   (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
  }
#define II(a, b, c, d, x, s, ac) { \
   (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
  }
//---------------------------------------------------------------------------
// POINTER defines a generic pointer type
typedef unsigned char *POINTER;
// UINT2 defines a two byte word
typedef unsigned short int UINT2;
// UINT4 defines a four byte word
typedef unsigned long int UINT4;
//---------------------------------------------------------------------------
class CMD5 {
private :
        // MD5 context
        typedef struct {
                UINT4 state[4]; // state (ABCD)
                UINT4 count[2]; // number of bits, modulo 2^64 (lsb first)
                unsigned char buffer[64]; // input buffer
        } MD5_CTX;

        void Memset(POINTER output,int value,unsigned int len);
        void Memcpy(POINTER output,POINTER input,unsigned int len);
        void Decode(unsigned char *output,UINT4 *input,unsigned int len);
        void Encode(UINT4 *output,unsigned char *input,unsigned int len);
        void Init(MD5_CTX *context);
        void Update(MD5_CTX *context,unsigned char *input,unsigned int inputLen);
        void Transform(UINT4 state[4],unsigned char block[64]);
        void Final(unsigned char *digest,MD5_CTX *context);
public :
        bool GetMD5Message(char *string,unsigned char digest[16]);
        bool GetMD5MessageToHex(char *string,unsigned char digest[32]);
        bool GetMD5File(char *filename,unsigned char digest[16]);
};
//---------------------------------------------------------------------------
#endif
